package com.xxchat.redis;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author Waicc
 */
@Component("redisUtils")
public class RedisUtils<V> {

    private static final Logger logger = LoggerFactory.getLogger(RedisUtils.class);

    @Resource
    private RedisTemplate<String, V> redisTemplate;

    /**
     * 删除缓存
     *
     * @param key 可以传一个或多个值
     */
    public void delete(String... key) {
        if(key != null && key.length > 0) {
            if (key.length == 1) {
                redisTemplate.delete(key[0]);
            } else {
                redisTemplate.delete(Arrays.asList(key));
            }
        }
    }

    /**
     * 获取缓存
     * @param key   键
     * @return  key为空返回null，否则返回缓存
     */
    public V get(String key) {
        return key == null ? null : redisTemplate.opsForValue().get(key);
    }

    /**
     * 普通缓存放入
     *
     * @param key   键
     * @param value 值
     * @return  true成功 false失败
     */
    public boolean set(String key, V value) {
        try {
            redisTemplate.opsForValue().set(key, value);
            return true;
        } catch (Exception e) {
            logger.error("设置redisKey:{},value:{}失败", key, value);
            return false;
        }
    }

    /**
     * 普通缓存放入并设置过期时间
     *
     * @param key   键
     * @param value 值
     * @param time  时间（秒） time要大于0 如果time小于等于0 表示无期限
     * @return  true成功 false失败
     */
    public boolean setex(String key, V value, long time) {
        try {
            if (time > 0) {
                redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
            } else {
                set(key, value);
            }
            return true;
        } catch (Exception e) {
            logger.error("设置redisKey:{},value:{}失败", key, value);
            return false;
        }
    }

    /**
     * 设置 Redis 键过期时间
     *
     * @param key   键
     * @param time  时间（秒） time要大于0
     * @return  true成功 false失败
     */
    public boolean expire(String key, long time) {
        try {
            if (time > 0) {
                redisTemplate.expire(key, time, TimeUnit.SECONDS);
            }
            return true;
        } catch (Exception e) {
            logger.error("设置过期时间redisKey:{}失败", key);
            return false;
        }
    }

    /**
     * 获取队列
     *
     * @param key   键
     * @return  返回队列 List
     */
    public List<V> getQueueList(String key) {
        return redisTemplate.opsForList().range(key, 0, -1);
    }

    /**
     * 向 队列头部（左侧）插入一个元素
     * @param key   键
     * @param value 值
     * @param time  过期时间
     * @return  true成功 false失败
     */
    public boolean lpush(String key, V value, long time) {
        try {
            redisTemplate.opsForList().leftPush(key, value);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            logger.error("向队列插入元素redisKey:{}失败", key);
            return false;
        }
    }

    /**
     * 从队列中移除指定值的元素
     *
     * @param key   键
     * @param value 值
     * @return  成功返回移除数量 失败返回0
     */
    public long remove(String key, Object value) {
        try {
            Long removedCount = redisTemplate.opsForList().remove(key, 1, value);
            return removedCount != null ? removedCount : 0;
        } catch (Exception e) {
            logger.error("从队列中移除元素redisKey:{},value:{}失败", key, value);
            return 0;
        }
    }

    /**
     * 向 队列头部（左侧）批量插入多个元素
     * @param key       键
     * @param values    值
     * @param time      过期时间
     * @return  true成功 false失败
     */
    public boolean lpushAll(String key, List<V> values, long time) {
        try {
            redisTemplate.opsForList().leftPushAll(key, values);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            logger.error("批量插入元素redisKey:{},value:{}失败", key, values);
            return false;
        }
    }
}
